﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.ServiceProcess;
using System.Web.Script.Serialization;
using System.Windows.Forms;
using Microsoft.Win32;

namespace VOEISHubPushServiceClient
{
    public partial class Form1 : Form
    {
        
        private FormDirtyTracker _dirtyTracker;
        private int _evtLogThreadCount = 0;
        private bool _closeRequested = false;
        ShutDown frmShutDown = new ShutDown();

       

        public Form1()
        {
            InitializeComponent();
        }

        #region Form Actions

        private void Form1_Load(object sender, EventArgs e)
        {
            //Get the path to the service config file
            SetServiceConfigPath();

            //Set up our picture box correctly since I can't access the parent settings through the graphical IDE
            pbEventLogLoading.BackColor = System.Drawing.Color.Transparent;
            pbEventLogLoading.Parent = dataGridView1;
            pbEventLogLoading.Location = new Point((dataGridView1.Width / 2) - 50, (dataGridView1.Height / 2) - 50);

            //Set up our service controller so we can start and stop the service from the client
            ServiceController myController = new ServiceController("VOEIS Hub Push Service", System.Environment.MachineName.ToString());

            //Enable and start our timer
            timer1.Enabled = true;
            timer1_Tick(timer1, EventArgs.Empty);

            //Initialize a new dirty tracker so we can track whether anything has changed on the form
            _dirtyTracker = new FormDirtyTracker(this);

            //Populate our configuration values
            PopulateConfiguration(Properties.Settings.Default.VOEISHubPushServicePath.ToString());
        }

        private void SetServiceConfigPath()
        {
            try
            {
                string strPath = "";
                RegistryKey services = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services");
                if (services != null)
                {
                    strPath = "";
                    strPath = services.OpenSubKey("VOEIS Hub Push Service").GetValue("ImagePath").ToString();
                    strPath = strPath.Replace("\"", "");
                    strPath = strPath.Replace(".exe", ".exe.config");
                    Properties.Settings.Default.VOEISHubPushServicePath = strPath;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("VOEIS Hub Push Service Not Found", "Service Missing - application will now close.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                MessageBox.Show(ex.Message.ToString(), "Error");
                System.Environment.Exit(99);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _closeRequested = true;

            if (_dirtyTracker.IsDirty)
            {
                DialogResult result = MessageBox.Show("Changes have been made - do you wish to save them before exiting?", "Changes Detected", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                if (result == DialogResult.Yes)
                {
                    //Save all of the settings.
                    SaveConfiguration(Properties.Settings.Default.VOEISHubPushServicePath.ToString());

                    //Clear our dirty tracker
                    _dirtyTracker.IsDirty = false;
                }
            }

            //Make sure that we don't have any errant threads running, and if so, then wait on them
            if (_evtLogThreadCount > 0)
            {
                e.Cancel = true;
                Rectangle recScreen = Screen.GetWorkingArea(this);
                this.Hide();
                frmShutDown.Show();
                frmShutDown.Location = new Point((recScreen.Width/2)-(frmShutDown.Width/2),(recScreen.Height / 2) - (frmShutDown.Height / 2));
            }
            else
            {
                e.Cancel = false;
                frmShutDown.Close();
            }
        }        

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                ServiceController myController = new ServiceController("VOEIS Hub Push Service", System.Environment.MachineName.ToString());
                tslblStatusValue.Text = myController.Status.ToString();
                if (myController.Status == ServiceControllerStatus.StartPending || myController.Status == ServiceControllerStatus.StopPending)
                {
                    btnStartService.Enabled = false;
                    btnStopService.Enabled = false;
                    tslblStatusValue.ForeColor = Color.DarkOrange;
                }
                else if (myController.Status == ServiceControllerStatus.Running)
                {
                    btnStartService.Enabled = false;
                    btnStopService.Enabled = true;
                    tslblStatusValue.ForeColor = Color.Green;
                }
                else if (myController.Status == ServiceControllerStatus.Stopped)
                {
                    btnStartService.Enabled = true;
                    btnStopService.Enabled = false;
                    tslblStatusValue.ForeColor = Color.Red;
                }
            }
            catch (InvalidOperationException)
            {
                timer1.Stop();
                MessageBox.Show("The VOEIS Push Service is missing.  Please uninstall and reinstall the service and application.", "Service Unavailable", MessageBoxButtons.OK, MessageBoxIcon.Error);
                tslblStatusValue.Text = "Service Unavailable";
                tslblStatusValue.ForeColor = Color.Red;

            }
            catch (Exception ex)
            {
                timer1.Stop();
                MessageBox.Show(ex.Message.ToString());
                tslblStatusValue.Text = "Service Unavailable";
                tslblStatusValue.ForeColor = Color.Red;
            }
        }

        #endregion

        #region Menu Items

        //TODO: This call should probably run in a separate thread.
        private void getProjectDataTemplatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;

            SQLCommunicator sqlComm = new SQLCommunicator();
            string projectTemplates = "";
            try
            {
                ArrayList projectIDs = sqlComm.ListProjectIDs(getCurrentConnectionString());

                for (Int32 i = 0; i < projectIDs.Count; i++)
                {
                    projectTemplates = "********** Project ID " + projectIDs[i].ToString() + " **********";
                    projectTemplates += System.Environment.NewLine + GetProjectTemplates(projectIDs[i].ToString()) + Environment.NewLine;
                }

                APIResults apiRslts = new APIResults(projectTemplates);
                apiRslts.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString(), "Error executing API call", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }

        }

        private void saveEncryptedConfigurationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveEncryptedTemplateConfigDialog.ShowDialog();
        }

        private void saveEncryptedTemplateConfigDialog_FileOk(object sender, CancelEventArgs e)
        {
            //Check if the form is dirty, and if so, prompt for a save before saving the template
            if (_dirtyTracker.IsDirty == true)
            {
               DialogResult response = new DialogResult();
                response = MessageBox.Show("You must save your changes before saving this template.", "Changes detected", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
                if (response == System.Windows.Forms.DialogResult.OK)
                {
                    //Save the template
                    SaveConfiguration(Properties.Settings.Default.VOEISHubPushServicePath);}
                else
                {
                    MessageBox.Show("Save aborted!", "Aborted", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }  
            }
                    
            //Save the template
            ServiceConfigurationManager scm = new ServiceConfigurationManager();
            scm.SaveTemplate(Properties.Settings.Default.VOEISHubPushServicePath, saveEncryptedTemplateConfigDialog.FileName, true);                           
              
        }

        private void loadConfigurationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                //TODO: open a file dialog
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "Configuration Files|*.exe.config";
                ofd.ShowDialog();
                if (!File.Exists(ofd.FileName.ToString()))
                {
                    MessageBox.Show("Configuration file required :" + ofd.FileName, "File Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                string configTemplatePath = ofd.FileName.ToString();
                ServiceConfigurationManager scm = new ServiceConfigurationManager();
                scm.LoadTemplate(this, configTemplatePath);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString(), "Error loading configuration template.", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 abtBox = new AboutBox1();
            abtBox.ShowDialog();
        }

        private void saveConfigurationSettingsToServiceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveConfiguration(Properties.Settings.Default.VOEISHubPushServicePath.ToString());
        }

        private void exportConfigurationAsTemplateunencryptedToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveUnencryptedTemplateConfigDialog.ShowDialog();
        }

        private void saveUnencryptedTemplateConfigDialog_FileOk(object sender, CancelEventArgs e)
        {
            //Check if the form is dirty, and if so, prompt for a save before saving the template
            if (_dirtyTracker.IsDirty == true)
            {
                DialogResult response = new DialogResult();
                response = MessageBox.Show("You must save your changes before saving this template.", "Changes detected", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
                if (response == System.Windows.Forms.DialogResult.OK)
                {
                    //Save the template
                    SaveConfiguration(Properties.Settings.Default.VOEISHubPushServicePath);
                }
                else
                {
                    MessageBox.Show("Save aborted!", "Aborted", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
            }

            ServiceConfigurationManager scm = new ServiceConfigurationManager();
            scm.SaveTemplate(Properties.Settings.Default.VOEISHubPushServicePath, saveUnencryptedTemplateConfigDialog.FileName, false);
        }

        #endregion
        
        #region Service Control

        private void btnStartService_Click(object sender, EventArgs e)
        {
            ServiceController myController = new ServiceController("VOEIS Hub Push Service", System.Environment.MachineName.ToString());
            try
            {
                //Start the service
                myController.Start();      
          
                //Update the log
                StartEventLogThread();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }

            finally
            {
        
                tslblStatusValue.Text = myController.Status.ToString();
                Application.DoEvents();
            }

            }

        //TODO: I need to find a better way to kill child threads other than just waiting for them
        private void btnStopService_Click(object sender, EventArgs e)
        {
            ServiceController myController = new ServiceController("VOEIS Hub Push Service", System.Environment.MachineName.ToString());
            try
            {
                //Stop the service
                myController.Stop();

                //Update the log
                StartEventLogThread();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
            finally
            {
                tslblStatusValue.Text = myController.Status.ToString();
                Application.DoEvents();
            }
        }

        private void btnServiceUndo_Click(object sender, EventArgs e)
        {
            PopulateServiceControlTab(Properties.Settings.Default.VOEISHubPushServicePath.ToString());
        }

        #endregion

        //#region Observation Database Settings
        //comment here

        //private void cboServiceDatabase_DropDown(object sender, EventArgs e)
        //{
        //    if (cboServiceSQLServer.SelectedText != null)
        //    {
        //        //Change the cursor to signify the work being done
        //        this.Cursor = Cursors.WaitCursor;
                
        //        //Clear the combobox
        //        cboServiceDatabase.Items.Clear();

        //        SQLCommunicator communicator = new SQLCommunicator();
        //        DataTable table = new DataTable();

        //        if (radServiceWindowsAuthentication.Checked == true)
        //        {
        //            //TODO: If a user enters incorrect server parameters, this crashes with a NullReferenceException
        //            table = communicator.ListSqlDatabases(cboServiceSQLServer.Text.ToString(), "Windows", txtServiceDatabaseUserName.Text.ToString(), txtServiceDatabasePassword.Text.ToString());
        //        }
        //        else
        //        {
        //            if (txtServiceDatabaseUserName.TextLength > 0 && txtServiceDatabaseUserName.TextLength > 0)
        //            {
        //                table = communicator.ListSqlDatabases(cboServiceSQLServer.SelectedItem.ToString(), "SQL", txtServiceDatabaseUserName.Text.ToString(), txtServiceDatabasePassword.Text.ToString());
        //            }
        //            else
        //            {
        //                MessageBox.Show("You must enter a username and password to continue, or choose a different authentication method.");
        //                this.Cursor = Cursors.Default;
        //                return;
        //            }
        //        }

        //        foreach (System.Data.DataRow row in table.Rows)
        //        {
        //            cboServiceDatabase.Items.Add(row[0].ToString());
        //        }
        //        this.Cursor = Cursors.Default;
        //    }
        //    else
        //    {
        //        MessageBox.Show("You must select a database first.");
        //    }
            
        //}        

        //private void cboObservationSQLServer_DropDown(object sender, EventArgs e)
        //{
        //    //TODO: Add code to enumerate the database on the selected server.  If the server is blank, then just exit the routine.
        //    if (cboObservationSQLServer.Items.Count == 0)
        //    {
        //        this.Cursor = Cursors.WaitCursor;
        //        cboObservationSQLServer.Items.Clear();

        //        SQLCommunicator communicator = new SQLCommunicator();
        //        DataTable table;
        //        String ServerName = "";

        //        table = communicator.ListSqlInstances();

        //        foreach (System.Data.DataRow row in table.Rows)
        //        {
        //            ServerName = "";
        //            ServerName = row[0].ToString();
        //            if (row[1].ToString() != null)
        //            {
        //                ServerName += "\\" + row[1].ToString();
        //            }
        //            cboObservationSQLServer.Items.Add(row[0].ToString() + "\\" + row[1].ToString());
        //        }
        //        this.Cursor = Cursors.Default;
        //    }
        //}

        //private void cboObservationDatabase_DropDown(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        if (cboObservationSQLServer.SelectedText != null)
        //        {
        //            //Change the cursor to signify the work being done
        //            this.Cursor = Cursors.WaitCursor;

        //            //Clear the combobox
        //            cboObservationDatabase.Items.Clear();

        //            SQLCommunicator communicator = new SQLCommunicator();
        //            DataTable table = new DataTable();

        //            if (radObservationWindowsAuthentication.Checked == true)
        //            {
        //                //TODO: If a user enters incorrect server parameters, this crashes with a NullReferenceException
        //                table = communicator.ListSqlDatabases(cboObservationSQLServer.Text.ToString(), "Windows", txtObservationDatabaseUserName.Text.ToString(), txtObservationDatabasePassword.Text.ToString());
        //            }
        //            else
        //            {
        //                if (txtObservationDatabaseUserName.TextLength > 0 && txtObservationDatabaseUserName.TextLength > 0)
        //                {
        //                    table = communicator.ListSqlDatabases(cboObservationSQLServer.SelectedItem.ToString(), "SQL", txtObservationDatabaseUserName.Text.ToString(), txtObservationDatabasePassword.Text.ToString());
        //                }
        //                else
        //                {
        //                    MessageBox.Show("You must enter a username and password to continue, or choose a different authentication method.");
        //                    this.Cursor = Cursors.Default;
        //                    return;
        //                }
        //            }

        //            foreach (System.Data.DataRow row in table.Rows)
        //            {
        //                cboObservationDatabase.Items.Add(row[0].ToString());
        //            }

        //        }
        //        else
        //        {
        //            MessageBox.Show("You must select a database first.");
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show(ex.Message.ToString());
        //    }
        //    finally
        //    {
        //        this.Cursor = Cursors.Default;
        //    }
        //}

        //private void cboObservationSQLServer_TextChanged(object sender, EventArgs e)
        //{
        //    cboObservationDatabase.Items.Clear();
        //    cboObservationDatabase.ResetText();
        //    radObservationWindowsAuthentication_CheckedChanged(sender, e);
        //}

        //private void radObservationWindowsAuthentication_CheckedChanged(object sender, EventArgs e)
        //{
        //    if (radObservationWindowsAuthentication.Checked)
        //    {
        //        lblObservationConnectionString.Text = "Data Source=" + cboObservationSQLServer.Text + ";Initial Catalog=" + cboObservationDatabase.Text + ";Integrated Security=SSPI;";
        //        txtObservationDatabaseUserName.Enabled = false;
        //        txtObservationDatabasePassword.Enabled = false;
        //    }
        //    else
        //    {
        //        lblObservationConnectionString.Text = "Data Source=" + cboObservationSQLServer.Text + ";Initial Catalog=" + cboObservationDatabase.Text + ";User Id=" + txtObservationDatabaseUserName.Text + ";Password=**********;";
        //        txtObservationDatabaseUserName.Enabled = true;
        //        txtObservationDatabasePassword.Enabled = true;
        //    }
        //}

        //private void cboObservationDatabase_TextChanged(object sender, EventArgs e)
        //{
        //    radObservationWindowsAuthentication_CheckedChanged(sender, e);
        //}

        //private void txtObservationDatabaseUserName_TextChanged(object sender, EventArgs e)
        //{
        //    radObservationWindowsAuthentication_CheckedChanged(sender, e);
        //}

        //private void txtObservationDatabasePassword_TextChanged(object sender, EventArgs e)
        //{
        //    radObservationWindowsAuthentication_CheckedChanged(sender, e);
        //}

        //private void btnObservationDatabaseTestConnection_Click(object sender, EventArgs e)
        //{
        //    Cursor = Cursors.WaitCursor;
        //    string connectionString = "";

        //    if (radObservationWindowsAuthentication.Checked)
        //    {
        //        connectionString = "Data Source=" + cboObservationSQLServer.Text + ";Initial Catalog=" + cboObservationDatabase.Text + ";Integrated Security=SSPI;";
        //    }
        //    else
        //    {
        //        connectionString = "Data Source=" + cboObservationSQLServer.Text + ";Initial Catalog=" + cboObservationDatabase.Text + ";User Id=" + txtObservationDatabaseUserName.Text + ";Password=" + txtObservationDatabasePassword.Text + ";";
        //    }

        //    SQLCommunicator sc = new SQLCommunicator();
        //    if (sc.TestConnection(connectionString) == true)
        //    {
        //        MessageBox.Show("Connection Success!", "Successful Connection", MessageBoxButtons.OK, MessageBoxIcon.Information);
        //    }
        //    Cursor = Cursors.Default;
        //}

        //private void btnObservationDBUndo_Click(object sender, EventArgs e)
        //{
        //    PopulateObservavtionsDatabaseTab(Properties.Settings.Default.VOEISHubPushServicePath);
        //    _dirtyTracker.IsDirty = false;
        //}

        //#endregion

        #region Service Database Settings

        private void radServiceWindowsAuthentication_CheckedChanged(object sender, EventArgs e)
        {
            if (radServiceWindowsAuthentication.Checked == true)
            {
                lblServiceConnectionString.Text = "Data Source=" + cboServiceSQLServer.Text + ";Initial Catalog=" + cboServiceDatabase.Text + ";Integrated Security=SSPI;";
                txtServiceDatabaseUserName.Enabled = false;
                txtServiceDatabasePassword.Enabled = false;
            }
            else
            {
                lblServiceConnectionString.Text = "Data Source=" + cboServiceSQLServer.Text + ";Initial Catalog=" + cboServiceDatabase.Text + ";User Id=" + txtServiceDatabaseUserName.Text + ";Password=**********;";
                txtServiceDatabaseUserName.Enabled = true;
                txtServiceDatabasePassword.Enabled = true;
            }
        }

        private void cboServiceSQLServer_DropDown(object sender, EventArgs e)
        {
            //TODO: Add code to enumerate the servers on the network.
            if (cboServiceSQLServer.Items.Count == 0)
            {
                this.Cursor = Cursors.WaitCursor;
                cboServiceSQLServer.Items.Clear();

                SQLCommunicator communicator = new SQLCommunicator();
                DataTable table;
                String ServerName = "";

                table = communicator.ListSqlInstances();

                foreach (System.Data.DataRow row in table.Rows)
                {
                    ServerName = "";
                    ServerName = row[0].ToString();
                    if (row[1].ToString() != null)
                    {
                        ServerName += "\\" + row[1].ToString();
                    }
                    cboServiceSQLServer.Items.Add(row[0].ToString() + "\\" + row[1].ToString());
                }
                this.Cursor = Cursors.Default;
            }
        }

        private void cboServiceSQLServer_TextChanged(object sender, EventArgs e)
        {
            cboServiceDatabase.Items.Clear();
            cboServiceDatabase.ResetText();
            radServiceWindowsAuthentication_CheckedChanged(sender, e);
        }

        private void cboServiceDatabase_TextChanged(object sender, EventArgs e)
        {
            radServiceWindowsAuthentication_CheckedChanged(sender, e);
        }

        private void cboServiceDatabase_DropDown(object sender, EventArgs e)
        {
            try
            {
                if (cboServiceSQLServer.SelectedText != null)
                {
                    //Change the cursor to signify the work being done
                    this.Cursor = Cursors.WaitCursor;

                    //Clear the combobox
                    cboServiceDatabase.Items.Clear();

                    SQLCommunicator communicator = new SQLCommunicator();
                    DataTable table = new DataTable();

                    if (radServiceWindowsAuthentication.Checked == true)
                    {
                        //TODO: If a user enters incorrect server parameters, this crashes with a NullReferenceException
                        table = communicator.ListSqlDatabases(cboServiceSQLServer.Text.ToString(), "Windows", txtServiceDatabaseUserName.Text.ToString(), txtServiceDatabasePassword.Text.ToString());
                    }
                    else
                    {
                        if (txtServiceDatabaseUserName.TextLength > 0 && txtServiceDatabaseUserName.TextLength > 0)
                        {
                            table = communicator.ListSqlDatabases(cboServiceSQLServer.SelectedItem.ToString(), "SQL", txtServiceDatabaseUserName.Text.ToString(), txtServiceDatabasePassword.Text.ToString());
                        }
                        else
                        {
                            MessageBox.Show("You must enter a username and password to continue, or choose a different authentication method.");
                            this.Cursor = Cursors.Default;
                            return;
                        }
                    }

                    foreach (System.Data.DataRow row in table.Rows)
                    {
                        cboServiceDatabase.Items.Add(row[0].ToString());
                    }

                }
                else
                {
                    MessageBox.Show("You must select a database first.");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void txtServiceDatabaseUserName_TextChanged(object sender, EventArgs e)
        {
            radServiceWindowsAuthentication_CheckedChanged(sender, e);
        }

        private void btnServiceDBUndo_Click(object sender, EventArgs e)
        {
            PopulateServiceDatabaseTab(Properties.Settings.Default.VOEISHubPushServicePath);
            _dirtyTracker.IsDirty = false;
        }

        private void btnServiceDatabaseTestConnection_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            string connectionString = "";

            if (radServiceWindowsAuthentication.Checked)
            {
                connectionString = "Data Source=" + cboServiceSQLServer.Text + ";Initial Catalog=" + cboServiceDatabase.Text + ";Integrated Security=SSPI;";
            }
            else
            {
                connectionString = "Data Source=" + cboServiceSQLServer.Text + ";Initial Catalog=" + cboServiceDatabase.Text + ";User Id=" + txtServiceDatabaseUserName.Text + ";Password=" + txtServiceDatabasePassword.Text + ";";
            }

            SQLCommunicator sc = new SQLCommunicator();
            if (sc.TestConnection(connectionString) == true)
            {
                MessageBox.Show("Connection Success!", "Successful Connection", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            Cursor = Cursors.Default;
        }

        #endregion

        #region Hub Settings
        private void btnHubUndo_Click(object sender, EventArgs e)
        {
            PopulateVOEISHubTab(Properties.Settings.Default.VOEISHubPushServicePath);
            _dirtyTracker.IsDirty = false;
        }
        #endregion

        #region Notification Settings
        private void cbxMailEnabled_CheckedChanged(object sender, EventArgs e)
        {
            if (cbxMailEnabled.Checked)
            {
                //enable all of the controls in this tab
                txtSMTPServer.Enabled = true;
                txtPort.Enabled = true;
                txtSender.Enabled = true;
                cbxSSL.Enabled = true;
                txtRecipients.Enabled = true;
                cbxUseAuthentication.Enabled = true;
                txtEmailUserName.Enabled = true;
                txtEmailPassword.Enabled = true;
                cbxUseAuthentication_CheckedChanged(sender, e);               

            }
            else
            {
                //disable all of the controls in this tab
                txtSMTPServer.Enabled = false;
                txtPort.Enabled = false;
                txtSender.Enabled = false;
                cbxSSL.Enabled = false;
                txtRecipients.Enabled = false;
                cbxUseAuthentication.Enabled = false;
                txtEmailUserName.Enabled = false;
                txtEmailPassword.Enabled = false;
                cbxUseAuthentication_CheckedChanged(sender, e);
            }
        }

        private void cbxUseAuthentication_CheckedChanged(object sender, EventArgs e)
        {
            if (cbxUseAuthentication.Checked)
            {
                txtEmailUserName.Enabled = true;
                txtEmailPassword.Enabled = true;
            }
            else
            {
                txtEmailPassword.Enabled = false;
                txtEmailUserName.Enabled = false;
            }
        }

        private void btnEmailSendTestMessage_Click(object sender, EventArgs e)
        {
            SmtpClient client = new SmtpClient(txtSMTPServer.Text);
            client.Port = Convert.ToInt32(txtPort.Text);
            client.EnableSsl = cbxSSL.Checked;

            if (cbxUseAuthentication.Checked)
            {
                System.Net.NetworkCredential creds = new System.Net.NetworkCredential(txtEmailUserName.Text, txtEmailPassword.Text);
                client.Credentials = creds;
            }

            MailMessage msg = new MailMessage(txtSender.Text, txtRecipients.Text);

            msg.Subject = "Test notification from the VOEIS Hub Push Service Manager";
            msg.Body = "Your settings are correct!";

            try
            {
                client.Send(msg);
                MessageBox.Show("Check your inbox!", "Test message sent", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString(), "Error sending test mail", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                client = null;
                msg = null;
            }
        }

        #endregion

        #region PopulateTabs
        //TODO: This should be run in a separate thread.
        //TODO:  This would probably be a hell of a lot more efficient if I just pulled a copy of the file into memory and read through the xml (but can I do that due to security constraints?).

        public void PopulateConfiguration(String configPath)
        {
            //TODO: Run this in a separate thread
            try
            {

                PopulateServiceControlTab(configPath);
                //PopulateObservavtionsDatabaseTab(configPath);
                PopulateServiceDatabaseTab(configPath);
                PopulateVOEISHubTab(configPath);
                PopulatePushResultsTab();
                PopulateNotificationsTab(configPath);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
        }

        private void PopulateServiceControlTab(String configPath)
        {
            ServiceConfigurationManager scm = new ServiceConfigurationManager();

            //Service Control Tab
            // Push Interval
            decimal totalTime = Convert.ToInt32(scm.ReadApplicationSetting("DataCheckInterval", configPath));
            cboDays.SelectedItem = Math.Floor(totalTime / 86400000).ToString();
            cboHours.SelectedItem = Math.Floor(((totalTime / 86400000) - Math.Floor(totalTime / 86400000)) * 24).ToString();
            cboMinutes.SelectedItem = Math.Round(((((totalTime / 3600000) - Math.Floor(totalTime / 3600000)) * 60) / 5) * 5).ToString();

            //Service Log
            StartEventLogThread();

            //Reset the dirty property
            _dirtyTracker.IsDirty = false;          
        }

        //private void PopulateObservavtionsDatabaseTab(String configPath)
        //{
        //    ServiceConfigurationManager scm = new ServiceConfigurationManager();

        //    //Observations Database Tab
        //    //Server
        //    cboObservationSQLServer.Text = scm.ReadApplicationSetting("ObservationSQLServer", configPath).ToString();

        //    //Database
        //    cboObservationDatabase.Text = scm.ReadApplicationSetting("ObservationDatabase", configPath).ToString();

        //    //Authentication (radio)
        //    if (scm.ReadApplicationSetting("ObservationAuthentication", configPath).ToString() == "Windows")
        //    {
        //        radObservationWindowsAuthentication.Checked = true;
        //    }
        //    else
        //    {
        //        radObservationSQLAuthentication.Checked = true;
        //    }

        //    //User Name
        //    txtObservationDatabaseUserName.Text = scm.ReadApplicationSetting("ObservationUserName", configPath).ToString();

        //    //Password
        //    txtObservationDatabasePassword.Text = scm.ReadApplicationSetting("ObservationPassword", configPath).ToString();

        //    //Reset the dirty property
        //    _dirtyTracker.IsDirty = false;
        //}

        private void PopulateServiceDatabaseTab(String configPath)
        {
            ServiceConfigurationManager scm = new ServiceConfigurationManager();

            //Push Service Database Tab
            //Server
            cboServiceSQLServer.Text = scm.ReadApplicationSetting("ServiceSQLServer", configPath).ToString();

            //Database
            cboServiceDatabase.Text = scm.ReadApplicationSetting("ServiceDatabase", configPath).ToString();

            //Authentication (radio)
            if (scm.ReadApplicationSetting("ServiceAuthentication", configPath).ToString() == "Windows")
            {
                radServiceWindowsAuthentication.Checked = true;
            }
            else
            {
                radServiceSQLAuthentication.Checked = true;
            }

            //User Name
            txtServiceDatabaseUserName.Text = scm.ReadApplicationSetting("ServiceUserName", configPath).ToString();

            //Password
            txtServiceDatabasePassword.Text = scm.ReadApplicationSetting("ServicePassword", configPath).ToString();

            //Reset the dirty property
            _dirtyTracker.IsDirty = false;
        }

        private void PopulateVOEISHubTab(String configPath)
        {
            ServiceConfigurationManager scm = new ServiceConfigurationManager();

            //VOEIS Hub Tab
            //API Key
            txtAPIKey.Text = scm.ReadApplicationSetting("APIKey", configPath).ToString();

            //Reset the dirty property
            _dirtyTracker.IsDirty = false;
        }

        private void PopulatePushResultsTab()
        {
            //Set up
            string connectionString = getCurrentConnectionString();
            //Check that the default server has been replaced
            if (!connectionString.Contains("YourServer\\YourDatabase"))
            {
                SQLCommunicator sqlComm = new SQLCommunicator();

                //Get a dictionary containing the datasets and syncID's
                Dictionary<string, string> dictionary = new Dictionary<string, string>();
                dictionary = sqlComm.ListDataSets(connectionString);

                //bind the dictionary to the combobox
                if (dictionary.Count > 0)
                {
                    cboPushResultsDataStreams.DataSource = new BindingSource(dictionary, null);
                    cboPushResultsDataStreams.DisplayMember = "Value";
                    cboPushResultsDataStreams.ValueMember = "Key";
                    cboPushResultsDataStreams_SelectedIndexChanged(sqlComm, null);
                }
            }
            else
            {
                MessageBox.Show("It appears that you have not updated your service settings." + Environment.NewLine + 
                    "Be sure to do so and save your settings before starting your service.", "Service Initialization", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void cboPushResultsDataStreams_DropDown(object sender, EventArgs e)
        {
            PopulatePushResultsTab();
        }

        private void cboPushResultsDataStreams_SelectedIndexChanged(object sender, EventArgs e)
        {
            SQLCommunicator sqlComm = new SQLCommunicator();
            string connectionString = "";
            if (radServiceWindowsAuthentication.Checked)
            {
                connectionString = "Data Source=" + cboServiceSQLServer.Text + ";Initial Catalog=" + cboServiceDatabase.Text + ";Integrated Security=SSPI;";
            }
            else
            {
                connectionString = "Data Source=" + cboServiceSQLServer.Text + ";Initial Catalog=" + cboServiceDatabase.Text + ";User Id=" + txtServiceDatabaseUserName.Text + ";Password=" + txtServiceDatabasePassword.Text + ";";
            }

            //Deserialize the json string
            //Example: {"total_records_saved":8,"last_record":{"created_at":"2011-03-07T20:20:28-07:00","timestamp":"2011-01-19T13:00:00-07:00","updated_at":"2011-03-07T20:20:28-07:00","published":false,"units":"NA","string_value":"6.12","id":42,"sensor_id":4,"value":6.12,"vertical_offset":-0.512},"success":"File was parsed succesfully.","total_rows_parsed":8}
            string SyncID = cboPushResultsDataStreams.SelectedItem.ToString();
            KeyValuePair<string, string> kvp = (KeyValuePair<string, string>)cboPushResultsDataStreams.SelectedItem;
            string json = sqlComm.GetPushResults(connectionString, Int32.Parse(kvp.Key));

            if (json.Length > 0)
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();

                try
                {
                    IDictionary<string, object> JSONDictionary = serializer.Deserialize<IDictionary<string, object>>(json);
                    txtPushResults.Text = "";
                    txtPushResults.Text = ParseJSON(JSONDictionary);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message.ToString());
                }
            }
            //Reset the dirty property
            _dirtyTracker.IsDirty = false;
        }

        private void PopulateNotificationsTab(String configPath)
        {
            ServiceConfigurationManager scm = new ServiceConfigurationManager();

            //Notifications Tab
            //MailEnabled
            cbxMailEnabled.Checked = Convert.ToBoolean(scm.ReadApplicationSetting("MailEnabled", configPath));

            //SMTP Server
            txtSMTPServer.Text = scm.ReadApplicationSetting("MailServer", configPath).ToString();

            //Port
            txtPort.Text = scm.ReadApplicationSetting("MailPort", configPath).ToString();
            
            //Sender
            txtSender.Text = scm.ReadApplicationSetting("ServiceEmail", configPath).ToString();

            //Recipients
            txtRecipients.Text = scm.ReadApplicationSetting("MailRecipients", configPath).ToString();

            //SSL (checkbox)
            cbxSSL.Checked = Convert.ToBoolean(scm.ReadApplicationSetting("MailSSL", configPath).ToString());

            //MailAuthenticate (checkbox)
            cbxUseAuthentication.Checked = Convert.ToBoolean(scm.ReadApplicationSetting("MailAuthenticate", configPath).ToString());

            //User Name
            txtEmailUserName.Text = scm.ReadApplicationSetting("MailUserName", configPath).ToString();

            //Password
            txtEmailPassword.Text = scm.ReadApplicationSetting("MailPassword", configPath).ToString();

            //Enable or disable appropriately
            cbxMailEnabled_CheckedChanged(cbxMailEnabled, EventArgs.Empty);

            //Reset the dirty property
            _dirtyTracker.IsDirty = false;

        }

        private void StartEventLogThread()
        {
            //Start a thread to run the event log in
            System.Threading.Thread evtLogThread = new System.Threading.Thread(new System.Threading.ThreadStart(PopulateEventLogGrid));
            evtLogThread.Start(); 
            _evtLogThreadCount++;           
        }

        private void PopulateEventLogGrid()
        {
            pbEventLogLoading.BeginInvoke((MethodInvoker)delegate() { pbEventLogLoading.Visible = true; });

            object query = QueryEventLog();

            if (!_closeRequested)
            {
                dataGridView1.BeginInvoke((MethodInvoker)delegate() { dataGridView1.DataSource = query; });

                pbEventLogLoading.BeginInvoke((MethodInvoker)delegate() { pbEventLogLoading.Visible = false; });
            }

            Invoke(new EventHandler(EventLogClose));
        }

        private object QueryEventLog()
        {
            System.Diagnostics.EventLog evtLog = new System.Diagnostics.EventLog();
            evtLog.Log = "Application";
            evtLog.MachineName = System.Environment.MachineName.ToString();

            try
            {
                var query = from EventLogEntry el in evtLog.Entries
                            where el.Source == "VOEIS Hub Push Service"
                            orderby el.TimeGenerated descending
                            select new
                            {
                                Time = el.TimeGenerated,
                                Source = el.Source,
                                Message = el.Message
                            };

                return query.ToList();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                object query = null;
                return query;
            }
        }

        private void EventLogClose(object o, EventArgs e)
        {
            _evtLogThreadCount--;

            if (_closeRequested)
            {
                this.Close();
            }
        }

        private string ParseJSON(IDictionary<string, object> JSONData)
        {
            string strJSON = "";
            try
            {
                foreach (KeyValuePair<string, object> kvp in JSONData)
                {
                    if (kvp.Value != null)
                    {

                        if (!(kvp.Value.GetType() == typeof(System.Collections.Generic.Dictionary<string, object>)))
                        {
                            //There can be null values in the kvp.value slot, and I need to account for that
                            strJSON = strJSON + kvp.Key.ToString() + ": ";

                            if (kvp.Value != null)
                            {
                                strJSON += kvp.Value.ToString();
                            }
                            else
                            {
                                strJSON += "";
                            }

                            strJSON += System.Environment.NewLine;
                        }
                        else
                        {
                            strJSON += ParseJSON((IDictionary<string, object>)kvp.Value);
                        }
                    }
                    else
                    {
                        strJSON += kvp.Key.ToString() + ": null" + System.Environment.NewLine;
                    }

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }

            return strJSON;
        }

        private void btnRefreshEventLog_Click(object sender, EventArgs e)
        {
            StartEventLogThread();
        }

        #endregion

        #region SaveTabs

        //TODO: Populate this section with code
        private void SaveServiceControlTab(String configPath)
        {
            //TODO: Add throttle setting based on interval time in the service select statement.
            ServiceConfigurationManager scm = new ServiceConfigurationManager();
            int totalTime = (Convert.ToInt32(cboDays.SelectedItem)*86400000) + (Convert.ToInt32(cboHours.SelectedItem)*3600000) + (Convert.ToInt32(cboMinutes.SelectedItem)*60000);
            

            //Push Interval - make sure that the interval is greater than 0
            if (totalTime > 0)
            {
                scm.SaveApplicationSetting("DataCheckInterval", Convert.ToString(totalTime), configPath);
            }
            else
            {
                MessageBox.Show("You must set an interval of 5 minutes or greater.", "Invalid Interval", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                PopulateServiceControlTab(configPath);
            }

            //Reset the dirty tracker
            _dirtyTracker.IsDirty = false;
                        
        }

        //private void SaveObservationsDatabaseTab(String configPath)
        //{
        //    ServiceConfigurationManager scm = new ServiceConfigurationManager();

        //    scm.SaveApplicationSetting("ObservationSQLServer", cboObservationSQLServer.Text, configPath);
        //    scm.SaveApplicationSetting("ObservationDatabase", cboObservationDatabase.Text, configPath);
        //    if (radObservationWindowsAuthentication.Checked)
        //    {
        //        scm.SaveApplicationSetting("ObservationAuthentication", "Windows", configPath);
        //    }
        //    else
        //    {
        //        scm.SaveApplicationSetting("ObservationAuthentication", "SQL", configPath);
        //    }
        //    scm.SaveApplicationSetting("ObservationUserName", txtObservationDatabaseUserName.Text, configPath);
        //    scm.SaveApplicationSetting("ObservationPassword", txtObservationDatabasePassword.Text, configPath);

        //    //Reset the dirty tracker
        //    _dirtyTracker.IsDirty = false;
            
        //}

        private void SaveServiceDatabaseTab(String configPath)
        {
            ServiceConfigurationManager scm = new ServiceConfigurationManager();
            //Settings
            scm.SaveApplicationSetting("ServiceSQLServer", cboServiceSQLServer.Text, configPath);
            scm.SaveApplicationSetting("ServiceDatabase", cboServiceDatabase.Text, configPath);
            if (radServiceWindowsAuthentication.Checked)
            {
                scm.SaveApplicationSetting("ServiceAuthentication", "Windows", configPath);
            }
            else
            {
                scm.SaveApplicationSetting("ServiceAuthentication", "SQL", configPath);
            }
            scm.SaveApplicationSetting("ServiceUserName", txtServiceDatabaseUserName.Text, configPath);
            scm.SaveApplicationSetting("ServicePassword", txtServiceDatabasePassword.Text, configPath);

            //Reset the dirty tracker
            _dirtyTracker.IsDirty = false;
        }

        private void SaveVOEISHubTab(String configPath)
        {
            ServiceConfigurationManager scm = new ServiceConfigurationManager();

            scm.SaveApplicationSetting("APIKey", txtAPIKey.Text, configPath);

            //Reset the dirty tracker
            _dirtyTracker.IsDirty = false;
            
        }

        private void SaveNotificationsTab(String configPath)
        {
            ServiceConfigurationManager scm = new ServiceConfigurationManager();

            scm.SaveApplicationSetting("MailEnabled", cbxMailEnabled.Checked.ToString(), configPath);
            scm.SaveApplicationSetting("MailServer", txtSMTPServer.Text, configPath);
            scm.SaveApplicationSetting("MailPort", txtPort.Text, configPath);
            scm.SaveApplicationSetting("ServiceEmail", txtSender.Text, configPath);
            scm.SaveApplicationSetting("MailRecipients", txtRecipients.Text, configPath);
            scm.SaveApplicationSetting("MailSSL", cbxSSL.Checked.ToString(), configPath);
            scm.SaveApplicationSetting("MailAuthenticate", cbxUseAuthentication.Checked.ToString(), configPath);
            scm.SaveApplicationSetting("MailUserName", txtEmailUserName.Text, configPath);
            scm.SaveApplicationSetting("MailPassword", txtEmailPassword.Text, configPath);

            //Reset the dirty tracker
            _dirtyTracker.IsDirty = false;
            
        }

        private void SaveConfiguration(String configPath)
        {
            try
            {
                //Stop Service and wait for stop response
                ServiceController myController = new ServiceController("VOEIS Hub Push Service", System.Environment.MachineName.ToString());
                ServiceControllerStatus initStatus = myController.Status;
                if (initStatus == ServiceControllerStatus.Running)
                {
                    myController.Stop();
                }

                //TODO: I need to check the controller state here before moving on, otherwise I get an error when trying to start the service.
                SaveServiceControlTab(configPath);
                //SaveObservationsDatabaseTab(configPath);
                SaveServiceDatabaseTab(configPath);
                SaveVOEISHubTab(configPath);
                SaveNotificationsTab(configPath);
                _dirtyTracker.IsDirty = false;

                //Restart service if required
                if (initStatus == ServiceControllerStatus.Running)
                {
                    myController.Start();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString(), "Error saving configuration.", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion

        #region General Methods
        public string GetHubURL()
        {
            ServiceConfigurationManager scm = new ServiceConfigurationManager();

            string configPath = Properties.Settings.Default.VOEISHubPushServicePath.ToString();

            string HubURL = scm.ReadApplicationSetting("VOEISHubURL", configPath).ToString();

            return HubURL;
        }

        public string GetProjectTemplates(string ProjectID)
        {
            //Set up some of our basic variables
            string BaseHubURL = GetHubURL();
            var HubURL = BaseHubURL.Replace("&lt;projectID&gt;", ProjectID) + "get_project_data_templates.json?";
            
            //Create the web request and set some basic parameters
            HttpWebRequest request = default(HttpWebRequest);
            WebResponse response = null;
            StreamReader reader = default(StreamReader);
            string retString = "";

            try
            {
                // Submit the request
                request = (HttpWebRequest)WebRequest.Create(HubURL.ToString());

                // Get response  
                response = (HttpWebResponse)request.GetResponse();

                // Get the response stream into a reader  
                reader = new StreamReader(response.GetResponseStream());

                //Save the response to a string
                string str = reader.ReadToEnd();

                //str = "[{""name"":""SandboxTest_003"",""updated_at"":""2011-02-21T09:24:52-06:00"",""id"":1,""type"":""Sensor"",""filename"":""temp_data/Mon Feb 21 09:19:40 -0700 2011HLSandboxFile_003.txt"",""start_line"":2,""description"":""Template creation of a simple file so that I can try a curl command and get the header actions for the service I am writing.""},{""name"":""Sandbox4"",""updated_at"":""2011-02-28T13:11:18-06:00"",""id"":2,""type"":""Sensor"",""filename"":""temp_data/Mon Feb 28 13:10:57 -0700 2011HLSandboxFile_003.csv"",""start_line"":2,""description"":""""},{""name"":""Sandbox5"",""updated_at"":""2011-02-28T14:25:32-06:00"",""id"":3,""type"":""Sensor"",""filename"":""temp_data/Mon Feb 28 14:25:15 -0700 2011HLSandboxFile_003.csv"",""start_line"":2,""description"":""""},{""name"":""HBSSandbox_004"",""updated_at"":""2011-03-02T14:26:12-06:00"",""id"":4,""type"":""Sensor"",""filename"":""temp_data/Wed Mar 02 14:21:20 -0700 2011HLSandboxFile_004.txt"",""start_line"":1,""description"":""Sandbox file containing no header, local date and time, depth offset, and tempc.  This is used for testing so that I can get a template, perform cURL, monitor with fiddler, and reproduce the headers in .NET.""}]"
                //Deserialize the json string
                if (str.Length > 0)
                {
                    try
                    {
                        JavaScriptSerializer serializer = new JavaScriptSerializer();
                        dynamic lstDataTemplates = serializer.DeserializeObject(str);
                        str = null;
                        foreach (object obj in lstDataTemplates)
                        {
                            foreach (KeyValuePair<string, object> kvp in (IDictionary<string, object>)obj)
                            {
                                retString = retString + kvp.Key.ToString() + ": " + kvp.Value.ToString() + System.Environment.NewLine;
                            }
                            retString = retString + System.Environment.NewLine;
                        }

                    }
                    catch (Exception ex)
                    {
                        //Catch our errors and write them to the event log and send an email
                        System.Diagnostics.EventLog.WriteEntry("VOEIS Hub Push Service - cURL Push", "Error uploading file: " + System.Environment.NewLine + ex.Message.ToString());
                    }
                }

            }
            catch (Exception ex)
            {
                //Catch our errors and write them to the event log and send an email
                System.Diagnostics.EventLog.WriteEntry("VOEIS Hub Push Service - cURL Push", "Error uploading file: " + System.Environment.NewLine + ex.Message.ToString());

                //Make sure that we close the response if it is still alive
                if (response != null)
                {
                    response.Close();
                    response = null;
                }

            }
            finally
            {
                //Make sure that we close our response
                request = null;
            }

            return retString;
        }

        private string getCurrentConnectionString()
        {
            string connectionString = "";

            if (radServiceWindowsAuthentication.Checked)
            {
                connectionString = "Data Source=" + cboServiceSQLServer.Text + ";Initial Catalog=" + cboServiceDatabase.Text + ";Integrated Security=SSPI;";
            }
            else
            {
                connectionString = "Data Source=" + cboServiceSQLServer.Text + ";Initial Catalog=" + cboServiceDatabase.Text + ";User Id=" + txtServiceDatabaseUserName.Text +";Password=" + txtServiceDatabasePassword.Text + ";";
            }

            return connectionString;
        }
        #endregion
    }
    }


